/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.gylang.springmini.registry;

import com.gylang.springmini.factory.ConfigurableBeanFactory;
import com.gylang.springmini.support.BeanDefinition;
import org.springframework.lang.Nullable;

/**
 * 为共享 bean 实例定义注册表的接口。 可以通过BeanFactory实现来实现，以便以统一的方式公开它们的单例管理工具
 * <p>The {@link ConfigurableBeanFactory} i
 * @author gylang
 */
public interface SingletonBeanRegistry extends BeanDefinitionRegistry {

    /**
     * 在给定的 bean 名称下，在 bean 注册表中将给定的现有对象注册为单例。
     * 给定的实例应该被完全初始化； 注册表不会执行任何初始化回调（特别是，它不会调用 InitializingBean 的afterPropertiesSet方法）。
     * 给定的实例也不会收到任何销毁回调（如 DisposableBean 的destroy方法）。
     * 在完整的 BeanFactory 中运行时：如果您的 bean 应该接收初始化和/或销毁回调，则注册 bean 定义而不是现有实例。
     * 通常在注册表配置期间调用，但也可用于单例的运行时注册。 因此，注册表实现应该同步单例访问； 如果它支持 BeanFactory 对单例的惰性初始化，无论如何它都必须这样做。
     *
     * @param beanName        bean名称
     * @param singletonObject 单例对象
     */
    void registerSingleton(String beanName, Object singletonObject);

    /**
     * 返回在给定名称下注册的（原始）单例对象。
     * 只检查已经实例化的单例； 不返回尚未实例化的单例 bean 定义的对象。
     * 此方法的主要目的是访问手动注册的单例（请参阅registerSingleton ）。 也可用于以原始方式访问由已创建的 bean 定义定义的单例。
     * 注意：此查找方法不知道 FactoryBean 前缀或别名。 在获取单例实例之前，您需要先解析规范的 bean 名称。
     *
     * @param beanName 查询的单例名称
     * @return 已注册的单例对象, or {@code null} 找不到单例对象
     */
    @Nullable
    Object getSingleton(String beanName);

    /**
     * 合并bean的声明定义, 定义在父类上面的依赖需要和定义需要合并到子类之上
     * @param beanName bean的名称
     * @return bean的定义
     */
    BeanDefinition mergeBeanDefinition(String beanName);

    /**
     * 检查此注册表是否包含具有给定名称的单例实例。
     * 只检查已经实例化的单例； 对于尚未实例化的单例 bean 定义，不返回true 。
     * 此方法的主要目的是检查手动注册的单例（请参阅registerSingleton ）。 还可用于检查是否已经创建了由 bean 定义定义的单例。
     * 要检查 bean 工厂是否包含具有给定名称的 bean 定义，请使用 ListableBeanFactory 的containsBeanDefinition 。
     * 调用containsBeanDefinition和containsSingleton回答特定的 bean 工厂是否包含具有给定名称的本地 bean 实例。
     * 使用 BeanFactory 的containsBean进行常规检查，工厂是否知道具有给定名称的 bean（无论是手动注册的单例实例还是由 bean 定义创建的），
     * 还检查祖先工厂。 此查找方法不知道 FactoryBean 前缀或别名。 在检查单例状态之前，您需要先解析规范 bean 名称。
     *
     * @param beanName 查询单例的名称
     * @return 如果通过名称查询该单例返回为true
     */
    boolean containsSingleton(String beanName);

    /**
     * 返回在此注册表中注册的单例 bean 的名称。
	 * 只检查已经实例化的单例； 不返回尚未实例化的单例 bean 定义的名称。
	 * 此方法的主要目的是检查手动注册的单例（请参阅registerSingleton ）。 还可用于检查已创建由 bean 定义定义的哪些单例。
     *
     * @return 返回单例名称数组 (不会为 {@code null})
     * @see #registerSingleton
     */
    String[] getSingletonNames();

    /**
     * 返回在此注册表中注册的单例 bean 的数量。
	 * 只检查已经实例化的单例； 不计算尚未实例化的单例 bean 定义。 此方法的主要目的是检查手动注册的单例（请参阅registerSingleton ）。
	 * 也可用于计算已创建的 bean 定义所定义的单例数。
     *
     * @return t单例bean的数量
     */
    int getSingletonCount();

    /**
     * 返回此注册表使用的单例互斥锁（用于外部协作者）。
     *
     * @return 互斥锁对象 (不会为 {@code null})
     * @since 4.2
     */
    Object getSingletonMutex();

}
